// Copyright (c) 2023 CHANGLEI. All rights reserved.

library decorator;

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:tverify/src/extensions.dart';
import 'package:tverify/src/generated/assets.dart';
import 'package:tverify/src/ui_view.dart';

part 'ui_config.dart';

part 'ui_model.dart';

/// Created by changlei on 2023/8/23.
///
/// 自定义页面配置
sealed class UIDecorator implements Codable {
  /// 自定义页面配置
  const UIDecorator();

  /// 适配
  factory UIDecorator.adaptive(
    BuildContext context, {
    Color textColor = CupertinoColors.label,
    Color? privacyNavBgColor,
    String? privacyContentText,
    ({String name, String url})? userAgreement,
    ({String name, String url})? privacyPolicy,
    UIImage? logo,
    UIImage? background,
    String? welcomeText,
    VoidCallback? onSwitch,
    VoidCallback? onClose,
  }) {
    final constructor = switch (Theme.of(context).platform) {
      TargetPlatform.android => UIConfig.adaptive,
      TargetPlatform.iOS => UIModel.adaptive,
      _ => throw PlatformException(code: 'unsupported_platform'),
    };
    return constructor.call(
      context,
      textColor: textColor,
      privacyNavBgColor: privacyNavBgColor,
      privacyContentText: privacyContentText,
      userAgreement: userAgreement,
      privacyPolicy: privacyPolicy,
      logo: logo,
      background: background,
      welcomeText: welcomeText,
      onSwitch: onSwitch,
      onClose: onClose,
    );
  }

  /// 加载Asset，放在assets/images/路径下
  static UIImage loadAsset(BuildContext context, String key, {String? package}) {
    final devicePixel = MediaQuery.devicePixelRatioOf(context);
    final devicePixelRatio = devicePixel.floorToDouble().clamp(1.0, 3.0);
    return UIImage.asset(Assets.images('${devicePixelRatio}x/$key'), package: package);
  }

  /// 自定义[UIView]
  List<UIView> get _views;

  @override
  Map<String, dynamic> toMap();
}

/// 扩展所有事件
extension DecoratorCallbacks on UIDecorator {
  /// 所有点击事件
  Map<String, VoidCallback> get allCallbacks {
    final callbacks = <String, VoidCallback>{};
    void visitor(UIView view) {
      if (view.onPressed != null) {
        callbacks[view.id] = view.onPressed!;
      }
      final children = view is UIViewGroup ? view.children : null;
      if (children != null) {
        children.forEach(visitor);
      }
    }

    _views.forEach(visitor);
    return Map.unmodifiable(callbacks);
  }
}

/// 语言
enum AuthLanguageType {
  /// 简体中文
  simplifiedChinese,

  /// 繁体中文
  traditionalChinese,

  /// 英文
  english,
}

/// An object that provides access to the font’s characteristics.
final class UIFont implements Codable {
  /// An object that provides access to the font’s characteristics.
  const UIFont({
    required this.fontSize,
    this.fontWeight,
  });

  /// fontSize
  final double fontSize;

  /// fontWeight
  final FontWeight? fontWeight;

  @override
  Map<String, dynamic> toMap() {
    return <String, dynamic>{
      'fontSize': fontSize,
      'fontWeight': fontWeight?.value,
    };
  }
}

/// UIImage
final class UIImage implements Codable {
  /// UIImage.named
  const UIImage.named(String name)
      : _type = 'name',
        _data = name,
        _package = null,
        _size = null,
        _radius = null;

  /// rootBundle.load(key)
  const UIImage.asset(String asset, {String? package})
      : _type = 'asset',
        _data = asset,
        _package = package,
        _size = null,
        _radius = null;

  /// Uint8List
  const UIImage.data(Uint8List data)
      : _type = 'data',
        _data = data,
        _package = null,
        _size = null,
        _radius = null;

  /// Uint8List
  const UIImage.color(
    Color color, {
    Size size = const Size.square(1),
    double radius = 0,
  })  : _type = 'color',
        _data = color,
        _package = null,
        _size = size,
        _radius = radius;

  final String _type;
  final Object _data;
  final String? _package;
  final Size? _size;
  final double? _radius;

  @override
  Map<String, dynamic> toMap() {
    return <String, dynamic>{
      'type': _type,
      'data': switch (_data) {
        Color() => (_data as Color).toMap(),
        _ => _data,
      },
      'package': _package,
      'size': _size?.toMap(),
      'radius': _radius,
    };
  }
}
